;(function ($, window) {
    var TableRow = function (data) {
        this.data = data;
        this.__childs__ = [];
        this.level = 0;
        this.hasChild = false;
        this.hasParent = false;
        this.index = 0;
        this.expand = false;
        this.checked = false;
        this.key = ''
    };
    TableRow.prototype = {
        setData: function (data) {
            this.data = data
        },
        getData: function () {
            return this.data
        },
        setKey: function (key) {
            this.key = key
        },
        setHasChild: function (hasChild) {
            this.hasChild = hasChild
        },
        hoverChild: function (ifshow) {
            var _this = this;
            this.expand = ifshow;
            if (ifshow) {
                this.__view__.find(".hover-child").text('-');
                $(this.__childs__).each(function (index, item) {
                    item.__view__.css("display", "")
                })
            } else {
                this.__view__.find(".hover-child").text('+');
                $(this.__childs__).each(function (index, item) {
                    item.__view__.hide();
                    item.hoverChild(ifshow)
                })
            }
        },
        render: function (templateSrc, childFild) {
            var _this = this;
            if (!childFild) {
                return this.renderNormal(templateSrc);
            }
            var __view__ = $(template.render(templateSrc, {
                "row": this.data,
                index: this.index,
                hasChild: this.hasChild,
                hasParent: this.hasParent
            }));
            if (this.__parent__ && !this.__parent__.expand) {
                __view__.hide()
            }
            var spaceEl = $("<span style='display: inline-block;width: " + (this.level * 18) + "px'></span>");
            __view__.find("td").eq(0).prepend(spaceEl);
            if (this.hasChild) {
                var x = this.expand ? "-" : "+";
                this.__hoverClildBtn__ = $("<span style='font-size: 18px;width:18px;display: inline-block;cursor: pointer' class='hover-child'>" + x + "</span>");
                spaceEl.after(this.__hoverClildBtn__);
                this.__hoverClildBtn__.click(function () {
                    _this.hoverChild($(this).text() === '+')
                })
            } else {
                spaceEl.after("<span style='display: inline-block;width: 18px'></span>")
            }
            if (this.__view__) {
                this.__view__.replaceWith(__view__)
            }
            this.__view__ = __view__;
            return this.__view__
        },
        renderNormal: function (templateSrc) {
            var _this = this;
            var __view__ = $(template.render(templateSrc, {
                "row": this.data,
                index: this.index,
                hasChild: this.hasChild,
                hasParent: this.hasParent
            }));
            if (this.__view__) {
                this.__view__.replaceWith(__view__)
            }
            this.__view__ = __view__;
            return this.__view__
        },
        setParent: function (parent) {
            this.hasParent = true;
            this.__parent__ = parent
        },
        getParent: function () {
            return this.__parent__
        },
        isParent: function () {
            return this.hasChild;
            /* return this.__childs__ && this.__childs__.length > 0;*/
        },
        addChilds: function (child) {
            this.__childs__.push(child)
        },
        setLevel: function (level) {
            this.level = level
        },
        setIndex: function (index) {
            this.index = index
        }
    };
    var $shTable = function (options) {
        var _this = this;
        this.ajaxVersion = 0;

        var defaultSetting = {
            templateId: undefined,
            template: {
                thead: undefined,
                tbody: undefined
            },
            tableHeaderEl: undefined,
            mounted: undefined,
            rowKey: "",
            childField: undefined,
            rowRenderAfter: function (row) {
            },
            rowCreated:function (row){

            },
            /*待注册事件*/
            tableEvent: {
                demoEvent: function (tableObj, row) {
                    _this.log("You triggered the default add event! data -->");
                    _this.log(JSON.stringify(row));
                }
            },
            filters: {
                testFilter: function (v, param) {
                    return "testFilter";
                }
            },
            showConditions: {},
            /*ajax方法配置*/
            ajax: {
                method: undefined,
                dataField: "list",
                /*参数构造器*/
                paramBuilder: function () {
                    _this.log("default paramBuilder!");
                    return {};
                },
                ajaxBefore: function (tableObj) {
                    _this.log("before ajax method!");
                },
                /*ajax成功回调*/
                ajaxSuccess: function (tableObj, data) {
                    _this.log("date load success!");
                },
                autoLoad: true,
                asyncDataFilter: function (data, defer, _this) {
                    /*页面真正渲染之前修改数据内容。修改完成后调用 defer.resolve 把修改后的结果传进去*/
                    defer.resolve(data);
                }
            },
            pagination: {
                open: true,
                pageSize: 10,
                /*1:普通,3:hbase*/
                pageModel: 1,
                showJump: true,
                defaultPage: 1,
                pageSizeList: [10, 20, 50],
                pageField: {
                    page: "page",
                    totalRecords: "totalRecords",
                    pageSize: "pageSize",
                    rowKey: "rowKey"
                }
            },
            /*数据渲染成功勾子*/
            renderCompleted: function (_tableObj) {
            },
            data: [],
            /*初始化成功回调*/
            initSuccess: function () {
                _this.log("table init success");
            },
            tableStyle: {class: "ui table sop-table-normal ", style: ""},
            pageStyle: {class: "s-pages sop-pages", style: ""},
            onChecked: function (tabobj, el, row) {

            },
            cascade: false,
            log: {level: "prod"},
            defaultChedked: [],
            renderEmpty: function (colspan, tabobj) {
                return "<tr style='text-align: center;' class='emptyTip'><td colspan='" + colspan + "'>查询无结果</td></tr>";
            }
        };
        this.template = undefined;
        this.options = $.extend(true, {}, defaultSetting, options);
        if (options.pagination && options.pagination.pageSizeList) {
            this.options.pagination.pageSizeList = options.pagination.pageSizeList
        }
        this.checkedRows = {};
        // todo 用户手动操作取消选择的列表，用于全局选中时排除某些行
        this.unCheckRows = {};
        this.hbaseStartRowKeyList = {1: undefined};
        this.rows = []
    };
    $shTable.prototype = {
        init: function () {
            this.v2mInputBind();
            if (this.options.filters) {
                $.extend(template.defaults.imports, this.options.filters)
            }
            var _this = this;
            $(this.options.defaultChedked).each(function (index, key) {
                _this.checkedRows[key] = {}
            });
            this.initTemplateSource();
            this.initViewTable();
            this.initPagination();
            this.bindThCheckedEvent();
            if (this.options.ajax.method) {
                this.initAjaxModel()
            } else {
                this.initNormalModel()
            }
            this.initSuccess();
            return this
        },
        initTemplateSource: function () {
            if (this.options.templateId) {
                this.template = $("#" + this.options.templateId);
                this.templateSource = this.template.text();
                var theadStart = this.templateSource.indexOf("<thead>") + 7;
                var theadLength = this.templateSource.indexOf("</thead>") - theadStart;
                this.templateSourcethead = this.templateSource.substr(theadStart, theadLength);
                var tbodyStart = this.templateSource.indexOf("<tbody>") + 7;
                var tbodyLength = this.templateSource.indexOf("</tbody>") - tbodyStart;
                this.templateSourceTr = this.templateSource.substr(tbodyStart, tbodyLength);
                this.template.hide()
            } else {
                this.templateSourcethead = this.options.template.thead;
                this.templateSourceTr = this.options.template.tbody;
            }
        },
        v2mInputBind: function () {
            var o = $.fn.val;
            $.fn.val = function () {
                var r = o.apply(this, arguments);
                if (this.is("[v2m-model]") && arguments.length > 0) {
                    this.trigger("change");
                    this.trigger("input")
                }
                return r
            }
        },
        initAjaxModel: function () {
            if (this.options.ajax.autoLoad) {
                this.doAjaxLoad(this.options.pagination.defaultPage)
            } else {
                this.showData([])
            }
        },
        initNormalModel: function () {
            if (this.options.pagination.open) {
                this.pageChange(1)
            } else {
                this.showData(this.options.data)
            }
        },
        initPagination: function () {
            if (this.options.pagination.open) {
                this.pageContainer = $("<div class='" + (this.options.pageStyle ? this.options.pageStyle.class : "") + "' style='" + (this.options.pageStyle ? this.options.pageStyle.style : "") + "'></div>");
                this.pager = jPage({
                    element: this.pageContainer,
                    page: this.options.pagination.defaultPage,
                    pageSize: this.options.pagination.pageSize,
                    showJump: true,
                    model: this.options.pagination.pageModel,
                    pageChangeCallback: this.pageChange.bind(this),
                    pageSizeList: this.options.pagination.pageSizeList
                })
            }
        },
        pageChange: function (index) {
            if (this.options.ajax.method) {
                this.doAjaxLoad(index)
            } else {
                this.doPagination(index, this.pager.pageSize, this.options.data)
            }
        },
        doPagination: function (pageNo, pageSize, array) {
            if (!array) {
                array = []
            }
            pageSize = parseInt(pageSize);
            if (!pageNo) {
                this.log("分页参数异常,请检查!")
            }
            var offset = (pageNo - 1) * pageSize;
            var data = (offset + pageSize >= array.length) ? array.slice(offset, array.length) : array.slice(offset, offset + pageSize);
            if (array.length > 0) {
                this.pager.setPage(pageNo, this.pager.pageSize, array.length);
                this.showData(data)
            } else {
                this.showData([]);
                this.pageContainer.empty()
            }
            return data
        },
        doAjaxLoad: function (index) {
            var _this = this;
            var params = {};
            if (this.options.ajax.paramBuilder) {
                params = this.options.ajax.paramBuilder();
                if (params === false) {
                    console.warn("params must be json object!!!");
                    return
                } else if (typeof params != 'object') {
                    params = {};
                    console.warn("params must be json object!!!")
                }
            }
            if (_this.pager) {
                if (index) {
                    params.page = index
                } else if (_this.pager.page) {
                    params.page = _this.pager.page
                } else {
                    params.page = 1
                }
                params[_this.options.pagination.pageField.pageSize] = _this.pager.pageSize;
                if (_this.options.pagination.pageModel == "3") {
                    params[_this.options.pagination.pageField.rowKey] = _this.hbaseStartRowKeyList[params.page];
                    params[_this.options.pagination.pageField.pageSize] = _this.pager.pageSize + 1
                }
            }
            if (this.options.ajax.ajaxBefore) {
                this.options.ajax.ajaxBefore(this)
            }
            var ajaxVersion = _this.ajaxVersion;
            this.options.ajax.method(params).success(function (data) {
                if (ajaxVersion < _this.ajaxVersion) {
                    return
                }
                _this.ajaxVersion = _this.ajaxVersion + 1;
                if (_this.options.ajax.asyncDataFilter) {
                    $.Deferred(function (defer) {
                        _this.options.ajax.asyncDataFilter(data, defer, _this)
                    }).promise().then(function (filterData) {
                        _this.afterAjaxSuccess(filterData)
                    })
                } else {
                    _this.afterAjaxSuccess(data)
                }
            }).error(function (error) {
                _this.log("data load fail!" + error)
            })
        },
        afterAjaxSuccess: function (responseData) {
            var _this = this;
            var data = responseData[this.options.ajax.dataField];
            _this.showData(data);
            if (_this.pager) {
                var pageNow = responseData[_this.options.pagination.pageField.page];
                if (_this.options.pagination.pageModel == "3") {
                    var canNext = false;
                    if (data) {
                        if (data.length > _this.pager.pageSize) {
                            canNext = true
                        } else if (data.length > 0) {
                            var lastItem = data[responseData.list.length - 1];
                            _this.hbaseStartRowKeyList[parseInt(pageNow) + 1] = lastItem[_this.options.pagination.pageField.rowKey]
                        }
                    }
                    _this.pager.setPage(pageNow, _this.pager.pageSize, null, canNext)
                } else if (responseData.totalRecords > 0) {
                    _this.pager.setPage(pageNow, _this.pager.pageSize, responseData.totalRecords)
                } else {
                    _this.pageContainer.empty()
                }
            }
            if (_this.options.ajax.ajaxSuccess) {
                _this.options.ajax.ajaxSuccess(_this, responseData)
            }
        },
        initViewTable: function () {
            var tableId = this.options.templateId + "_" + this.randomID(3);
            this.viewTable = $("<table class='" + (this.options.tableStyle ? this.options.tableStyle.class : "") + "' style='" + (this.options.tableStyle ? this.options.tableStyle.style : "") + "'></table>");
            this.viewTable.attr("id", tableId);
            this.thead = $("<thead></thead>");
            this.thead.append($(this.templateSourcethead));
            this.viewTable.append(this.thead);
            this.tbody = $("<tbody></tbody>");
            this.viewTable.append(this.tbody)
            if (this.options.renderEmpty) {
                var colspan = this.thead.find("th").length;
                this.emptyTr = $(this.options.renderEmpty(colspan, this));
            }
        },
        mount: function (dom, pageEl) {
            if (dom) {
                dom.empty();
                dom.append(this.viewTable)
            } else {
                if (this.options.templateId) {
                    this.template.after(this.viewTable)
                }
            }
            if (pageEl) {
                pageEl.html(this.pageContainer)
            } else {
                this.viewTable.after(this.pageContainer)
            }
            if (this.options.mounted) {
                this.options.mounted(this);
            }
            return this;
        },
        showData: function (data) {
            var _this = this;
            if (this.templateSource === "") {
                console.error("Your template is empty,Your template is empty,Determine if your template is loaded if your template is loaded");
                return
            }
            if (!data instanceof Array) {
                this.log("data请传入数组！")
            }
            if (!data) {
                data = this.options.data
            }
            this.tbody.empty();
            this.data = data;
            this.rows = [];
            if (data && data.length > 0) {
                _this.render(this.data, undefined, 0);
            } else {
                _this.renderEmpty()
            }

            _this.resolveCheckAll();
            if (this.options.renderCompleted) {
                this.options.renderCompleted(this)
            }
        },
        reRender: function () {
            this.showData(this.data);
        },
        render: function (data, parent, level) {
            var _this = this;
            $(data).each(function (index, item) {
                _this.renderItem(item, parent, level, index);
            })
        },
        renderEmpty: function () {
            if (this.data && this.data.length > 0 && this.emptyTr) {
                this.emptyTr.hide();
            } else {
                if (!this.tbody.find(this.emptyTr).length > 0) {
                    this.tbody.append(this.emptyTr);
                }
                this.emptyTr.show();
            }
        },
        renderItem: function (item, parent, level, index) {
            var row = new TableRow(item);
            if (parent) {
                row.setParent(parent);
                parent.addChilds(row)
            }
            row.setIndex(index);
            row.setLevel(level);
            row.expand = item.expand;
            row.setKey(item[this.options.rowKey]);
            row.setHasChild(this.options.childField && item[this.options.childField] && item[this.options.childField].length > 0);
            var rowEl = row.render(this.templateSourceTr, this.options.childField);
            this.renderShowConditions(row);
            this.tbody.append(rowEl);
            if (this.options.rowRenderAfter) {
                this.options.rowRenderAfter(row)
            }
            if (row.hasChild) {
                this.render(item[this.options.childField], row, level + 1);
            }
            this.bindEvent(row);
            this.rows.push(row)
        },
        /*条件渲染*/
        renderShowConditions: function (row) {
            var _this = this;
            var __view__ = row.__view__;
            __view__.find("[showConditions]").each(function (index, el) {
                var showConditions = $(this).attr("showConditions");
                var showConditionsConfigs = _this.options.showConditions[showConditions];
                if (showConditionsConfigs) {
                    var flag = true;
                    $(showConditionsConfigs).each(function (i, fn) {
                        if (!fn(row)) {
                            flag = false;
                        }
                    });
                    if (!flag) {
                        $(this).remove();
                    }
                }
            });

        },
        renderRow: function (row) {
            row.render(this.templateSourceTr, this.options.childField);
            if (this.options.rowRenderAfter) {
                this.options.rowRenderAfter(row)
            }
            this.bindEvent(row)
        },
        reload: function (data) {
            if (this.options.ajax.method) {
                this.doAjaxLoad()
            } else {
                this.options.data = data;
                this.initNormalModel()
            }
        },
        expandAll: function (ifexplnd) {
            if (ifexplnd) {
                $(this.rows).each(function (index, row) {
                    row.expand = true;
                    if (row.isParent()) {
                        row.__hoverClildBtn__.text("-")
                    }
                    row.__view__.show()
                })
            } else {
                $(this.rows).each(function (index, row) {
                    row.expand = false;
                    if (row.isParent()) {
                        row.__hoverClildBtn__.text("+")
                    }
                    if (row.__parent__) {
                        row.__view__.hide()
                    }
                })
            }
        },
        bindEvent: function (row) {
            this.bindTableEvent(row);
            this.bindTdCheckEventAndCache(row);
            this.bindV2mModel(row)
            if (this.options.rowCreated) {
                this.options.rowCreated(row)
            }
        },
        bindTableEvent: function (row) {
            var _this = this;
            $(row.__view__.find("[tableEvent]")).each(function (index, el) {
                var eventSetting = eval("(" + $(el).attr("tableEvent") + ")");
                if (eventSetting instanceof Array) {
                    $(eventSetting).each(function (eventIndex, setting) {
                        var event = _this.options.tableEvent[setting.fun];
                        if (event) {
                            $(el).bind(setting.type, function () {
                                _this.triggerEvent(event, row, this)
                            })
                        }
                    })
                } else {
                    var event = _this.options.tableEvent[eventSetting.fun];
                    if (event) {
                        $(el).bind(eventSetting.type, function () {
                            _this.triggerEvent(event, row, this)
                        })
                    }
                }
            })
        },
        getCheckedKeys: function () {
            return this.ObjectKeys(this.checkedRows)
        },
        getCheckedObject: function () {
            var _this = this;
            var checkRows = this.ObjectValues(this.checkedRows);
            var objs = [];
            $(checkRows).each(function (index, item) {
                var data = $.extend(true, {}, item.getData());
                if (_this.options.childField) {
                    delete data[_this.options.childField];
                }
                objs.push(data)
            });
            return objs
        },
        getCheckedRecursions: function () {
            var checkedRows = this.ObjectValues(this.checkedRows);
            var tops = [];
            var _this = this;
            var topRowsCache = [];
            $(checkedRows).each(function (index, row) {
                _this.getCheckedTopRows(row, topRowsCache)
            });
            /*封装数据*/
            $(topRowsCache).each(function (index, row) {
                var data = $.extend(true, {}, row.getData());
                _this.packageChildData(row, data);
                tops.push(data);
            });
            return tops
        },

        packageChildData: function (row, data) {
            var _this = this;
            if (row.isParent()) {
                var childs = [];
                $(row.__childs__).each(function (index, child) {
                    if (_this.hasCheckedChild(child)) {
                        var childData = $.extend(true, {}, child.getData());
                        _this.packageChildData(child, childData);
                        childs.push(childData)

                    }
                });
                data[this.options.childField] = childs;
            }
        },
        getCheckedTopRows: function (row, topRowsCache) {
            if (row.__parent__) {
                this.getCheckedTopRows(row.__parent__, topRowsCache)
            } else if (topRowsCache.indexOf(row) === -1) {
                topRowsCache.push(row)
            }
        },
        hasCheckedChild: function (row) {
            var data = row.getData();
            if (this.checkedRows[data[this.options.rowKey]]) {
                return true
            }
            if (row.__childs__) {
                for (var i = 0; i < row.__childs__.length; i++) {
                    if (this.hasCheckedChild(row.__childs__[i])) {
                        return true
                    }
                }
            }
            return false
        },
        push: function (item) {
            var _this = this;
            if (Array.isArray(item)) {
                $(item).each(function (index, it) {
                    _this.options.data.push(it)
                    if (!_this.options.pagination.open) {
                        _this.renderItem(it, undefined, 0, _this.options.data.length - 1);
                    }
                });
                if (!_this.options.pagination.open) {
                    _this.renderEmpty();
                }
            } else {
                _this.options.data.push(item)
                if (!_this.options.pagination.open) {
                    _this.renderItem(item, undefined, 0, _this.options.data.length - 1);
                    _this.renderEmpty();
                }
            }
            if (_this.options.pagination.open) {
                _this.pageChange(this.pager.page)
            }
        },
        remove: function (item) {
            var _this = this;
            $(_this.rows).each(function (index, row) {
                var data = row.getData();
                if (item[_this.options.rowKey] == data[_this.options.rowKey]) {
                    _this.removeRow(row);
                    return false;
                }
            });
        },
        removeRow: function (row) {
            var _this = this;
            var data = row.getData();
            var key = data[this.options.rowKey];
            delete this.checkedRows[key];
            row.__view__.remove();
            this.rows.splice(this.rows.indexOf(row), 1);
            var level = row.level;
            //清空parent中的数据
            if (this.options.childField && row.__parent__) {
                var parentData = row.__parent__.getData();
                $(row.__parent__.__childs__).each(function (i, item) {
                    var itemData = item.getData();
                    if (key == itemData[_this.options.rowKey]) {
                        row.__parent__.__childs__.splice(i, 1);
                        parentData[_this.options.childField].splice(i, 1);
                    }
                })
            } else {
                $(this.options.data).each(function (index, item) {
                    if (key == item[_this.options.rowKey]) {
                        _this.options.data.splice(index, 1);
                    }
                })
            }
            if (row.__childs__) {
                $(row.__childs__).each(function (index, r) {
                    _this.removeRow(r)
                });

            }
            this.resolveCheckAll();
            this.renderEmpty();
        },
        removeItem: function (key, fieldName) {
            var _this = this;
            $(_this.rows).each(function (index, row) {
                var item = row.getData();
                if (key == item[fieldName]) {
                    _this.removeRow(row);
                    return false;
                }

            });
            if (this.options.pagination.open) {
                this.pageChange(this.pager.page)
            }
        },
        /*不带层级的时候才可以使用*/
        removeByIndex: function (index) {
            var _this = this;
            this.options.data.splice(index, 1);
            var row = this.rows[index];
            row.__view__.remove();
            this.rows.splice(index, 1);
            $(this.rows).each(function (r_index, row) {
                row.setIndex(r_index);
                if (index <= r_index) {
                    _this.renderRow(row);
                }
            });
            this.resolveCheckAll();
        },
        /*获取当前展示数据*/
        getData: function (simple /*是否简单数据*/) {
            if(simple){
                return getSimpleData();
            }
            return this.data
        },
        get:function (key){
            var rows = this.rows;
            var res =undefined;
            var _this = this;
            $(rows).each(function (index, row) {
                var data = row.getData();
                if(data[_this.options.rowKey]==key){
                    res=row;
                    return;
                }
            });
            return res;
        },
        getSimpleData: function () {
            var rows = this.rows;
            var res = [];
            var _this = this;
            $(rows).each(function (index, row) {
                var item = $.extend(true, {}, row.getData());
                item[_this.options.childField] = undefined;
                res.push(item);
            });
            /*封装数据*/
            return res
        },
        /*获取所有数据包含前端分页*/
        getAllData: function () {
            if (this.options.ajax.method) {
                if (this.options.pagination.open) {
                    this.log("分页模式不支持此api!");
                    return null
                } else {
                    return this.getCurrentData()
                }
            }
            return this.options.data
        },
        clear: function () {
            this.options.data = [];
            if (this.options.pagination.open) {
                this.pageChange(this.pager.page)
            } else {
                this.showData(this.options.data)
            }
        },
        check: function (objOrKey) {
            var key;
            if (objOrKey instanceof Object) {
                key = objOrKey[this.options.rowKey];
            } else {
                key = objOrKey;
            }
            var row = this.findRowByKey(key);
            if (!row) {
                if (!objOrKey instanceof Object) {
                    this.log("未找到要选中的行，请传入对象！");
                    return;
                }
                row = new TableRow(objOrKey);
                row.setKey(key)
            }
            row.checked = true;
            this.checkedRows[key] = row;
            this.renderRow(row);
        },
        unCheck: function (objOrKey) {
            var key;
            if (objOrKey instanceof Object) {
                key = objOrKey[this.options.rowKey];
            } else {
                key = objOrKey;
            }
            var row = this.checkedRows[key];
            delete this.checkedRows[key];
            row.checked = false;
            this.renderRow(row);
        },
        findRowByKey: function (key) {
            var row = undefined;
            var _this = this;
            $(this.rows).each(function (index, item) {
                if (item.key === key) {
                    row = item;
                    return false;
                }
            });
            return row;
        },
        checkRecursions: function (itemObj, ifcheck, parent) {
            var key = itemObj[this.options.rowKey];
            if (!key) {
                return;
            }
            var row = this.findRowByKey(key);
            if (!row) {
                row = new TableRow(itemObj);
                row.setKey(key);
                if (parent) {
                    row.setParent(parent);
                    parent.addChilds(row)
                }
            }
            if (ifcheck) {
                this.checkedRows[key] = row
            } else {
                delete this.checkedRows[key]
            }
            var _this = this;
            if (this.options.childField && itemObj[this.options.childField] && itemObj[this.options.childField].length > 0) {
                row.setHasChild(true);
                $(itemObj[this.options.childField]).each(function (index, item) {
                    _this.checkRecursions(item, ifcheck, row)
                })
            }
            row.checked = ifcheck;
            this.renderRow(row);
        },
        bindThCheckedEvent: function () {
            var _this = this;
            var $th;
            if (this.options.tableHeaderEl) {
                $th = this.options.tableHeaderEl
            } else {
                $th = this.viewTable
            }
            $th.find("th [openCheck='true'][type=checkbox]").each(function (index, el) {
                $(this).change(function () {
                    var checked = $(this).is(':checked');
                    _this.checkAllData(_this.rows, checked);
                    _this.options.onChecked(_this, this)
                })
            })
        },
        checkAllData: function (rows, ifcheck) {
            var _this = this;
            $(rows).each(function (index, row) {
                var data = row.getData();
                var el = row.__view__.find("td [type=checkbox]");
                if (el.length > 0) {
                    row.checked = ifcheck;
                    row.indeterminate = false;
                    el[0].indeterminate = false;
                    if (ifcheck) {
                        el.attr("checked", true);
                    } else {
                        el.removeAttr("checked");
                    }
                    if (ifcheck) {
                        var key = data[_this.options.rowKey];
                        _this.checkedRows[key] = row
                    } else {
                        var key = data[_this.options.rowKey];
                        if (_this.checkedRows[key]) {
                            delete _this.checkedRows[key];
                        }
                    }
                }
                if (row.isParent()) {
                    _this.checkAllData(row.__childs__, ifcheck);
                }

            })
        },
        bindTdCheckEventAndCache: function (row) {
            var _this = this;
            if (row.__view__.find("[openCheck='true']").length > 0) {
                var checkEl = row.__view__.find("[openCheck='true']");
                var rowKey = checkEl.attr("row-key");
                _this.bindTdCheckEvent(checkEl, row, rowKey)
            } else {
                //移除选择框的场景也需要刷新选中列表中的缓存
                var data = row.getData();
                var key = data[_this.options.rowKey];
                if (_this.checkedRows[key] || row.checked === true) {
                    _this.checkedRows[key] = row
                }
            }
        },
        bindTdCheckEvent: function (checkEl, row, myrowKey) {
            var _this = this;
            var data = row.getData();
            var rowKey = _this.options.rowKey;
            if (myrowKey) {
                rowKey = myrowKey
            }
            if (!rowKey) {
                return
            }
            var key = data[rowKey];
            if (_this.checkedRows[key] || row.checked === true || data.checked === true) {
                checkEl.attr("checked", true);
                row.checked = true;
                _this.checkedRows[key] = row;
                /*子元素已经渲染完成，计算是否半选*/
                if (row.hasChild) {
                    _this.cascadeParent(row);
                }
            } else {
                checkEl.removeAttr("checked")
            }
            if (checkEl.length > 0) {
                checkEl.change(function () {
                    var checked = $(this).is(':checked');
                    if (checked) {
                        if (checkEl.attr("type") === "radio") {
                            _this.checkedRows = {}
                        }
                        _this.checkedRows[key] = row
                    } else {
                        delete _this.checkedRows[key]
                    }
                    row.checked = checked;
                    if (_this.options.cascade) {
                        _this.cascadeChild(row, checked);
                        _this.cascadeParent(row.__parent__);
                    }
                    if (_this.options.onChecked) {
                        _this.options.onChecked(_this, this, row)
                    }
                    if (checkEl.attr("type") === "checkbox") {
                        _this.resolveCheckAll()
                    }
                })
            }
        },
        cascadeChild: function (row, checked) {
            var _this = this;
            if (row.isParent()) {
                $(row.__childs__).each(function (index, child) {
                    var checkEl = child.__view__.find("[openCheck='true']");
                    var data = child.getData();
                    var key = data[_this.options.rowKey];
                    if (checked) {
                        checkEl.attr("checked", true);
                        _this.checkedRows[key] = child
                    } else {
                        delete _this.checkedRows[key];
                        checkEl.removeAttr("checked")
                    }
                    child.checked = checked;
                    if (child.isParent()) {
                        _this.cascadeChild(child, checked)
                    }
                })
            }
        },
        cascadeParent: function (parent) {
            if (parent) {
                var ifAllChildChecked = true;
                var checkedSize = 0;
                var indeterminateSize = 0;
                $(parent.__childs__).each(function (index, child) {
                    var result = child.__view__.find("[openCheck='true']").is(':checked');
                    if (!result) {
                        ifAllChildChecked = false;
                    } else {
                        checkedSize = checkedSize + 1;
                    }
                    if (child.indeterminate) {
                        indeterminateSize = indeterminateSize + 1;
                    }
                });
                var rowKey = this.options.rowKey;
                if (!rowKey) {
                    return
                }
                var data = parent.getData();
                var key = data[this.options.rowKey];
                if (ifAllChildChecked) {
                    this.checkedRows[key] = parent
                } else {
                    delete this.checkedRows[key]
                }
                var checkEl = parent.__view__.find("[openCheck='true']");
                checkEl.attr("checked", ifAllChildChecked);
                var indeterminate = false;
                if (indeterminateSize > 0 || (checkedSize !== 0 && checkedSize < parent.__childs__.length)) {
                    indeterminate = true;
                }
                checkEl.each(function (index, checkbox) {
                    checkbox.indeterminate = indeterminate;
                })
                parent.checked = ifAllChildChecked;
                parent.indeterminate = indeterminate;
                /*是否全选*/
                if (parent.__parent__) {
                    this.cascadeParent(parent.__parent__)
                }
            }
        },
        resolveCheckAll: function () {
            var $th;
            if (this.options.tableHeaderEl) {
                $th = this.options.tableHeaderEl
            } else {
                $th = this.viewTable
            }
            var checkedCheckboxLength = this.viewTable.find("td [type=checkbox]:checked").length;
            var checkboxLength = this.viewTable.find("td [type=checkbox]").length;
            var indeterminate = false;
            var checkAllEl = $th.find("th [openCheck='true'][type=checkbox]");
            if (checkedCheckboxLength === checkboxLength && checkboxLength != 0) {
                /*全选场景*/
                checkAllEl.attr("checked", true);
            } else {
                /*非全选场景*/
                checkAllEl.removeAttr("checked");
                if (checkedCheckboxLength > 0) {
                    indeterminate = true;
                }
            }
            checkAllEl.each(function (index, checkbox) {
                checkbox.indeterminate = indeterminate;
            })
        },
        bindV2mModel: function (row) {
            var _this = this;
            if (row.__view__.find("[v2m-model]").length > 0) {
                row.__view__.find("[v2m-model]").each(function (idx, el) {
                    var modelAttr = $(this).attr("v2m-model");
                    var v2mget = $(this).attr("v2m-model-get");
                    var event = _this.options.tableEvent[v2mget];
                    var setVal = function () {
                        var data = row.getData();
                        if (v2mget) {
                            if (event) {
                                data[modelAttr] = event(_this, row, el);
                            }
                        } else {
                            data[modelAttr] = el.value
                        }
                    };
                    //视图转model指责不可以反向操作
                    /*if (row.data[modelAttr]) {
                        el.value = row.data[modelAttr];
                        setVal();
                    } else {
                        setVal();
                    }*/
                    $(el).on("input onpropertychange change", function () {
                        setVal();
                    })
                })
            }
        },
        triggerEvent: function (event, row, _el) {
            event(this, row, _el)
        },
        initSuccess: function () {
            if (this.options.initSuccess) {
                this.options.initSuccess(this)
            }
        },
        randomID: function (randomLength) {
            return Number(Math.random().toString().substr(3, randomLength) + new Date().getTime()).toString(36)
        },
        log: function (msg) {
            if (this.options.log.level == "debugger") {
                console.log(msg)
            }
        },
        ObjectKeys: function (obj) {
            var res = [];
            for (var key in obj) {
                res.push(key)
            }
            return res;
        },
        ObjectValues: function (obj) {
            var res = [];
            for (var key in obj) {
                res.push(obj[key])
            }
            return res;
        }
    };
    window.shTable = function (options) {
        return new $shTable(options).init()
    }
}(jQuery, window));